#include <stdio.h>
#include "Thread_Pool.h"
#include "Thread_Pool_Worker.h"
#include "stdlib.h"
#include "signal.h"
#include "unistd.h"
#include "Thread_Pool_Manager.h"

#define    FACTOR   1.5
#define    MIN_IDLE 2
#define    ONCE_ADD_THRD 2
/**
 * @function:最优化线程数量。
 * @arg: in fact is a poolp
 * */
void *ThreadPool_ManagerFunc(void * arg)
{
    int ret = 0;
    Thread_Poolp poolp = (Thread_Pool *)arg;
    int live_thrd = 0;
    int busy_thrd = 0;
    int task_num = 0;
    int i = 0;
    while(!poolp->shutdown)
    {
        sleep(5);   //大约每5s执行一次
        
        //1-取出线程池中的相关数据（活跃的线程数 & 任务队列的成员数）
        pthread_mutex_lock(&poolp->pool_mutex);
        live_thrd = poolp->live_thrd_num;
        task_num = poolp->task_num;
        pthread_mutex_unlock(&poolp->pool_mutex);

        pthread_mutex_lock(&poolp->busy_mutex);
        busy_thrd = poolp->busy_thrd_num;
        pthread_mutex_unlock(&poolp->busy_mutex);
        
        //2-依据所得到的数据，判断增加线程，还是减少线程，还是不做任何事。
        //2-1 减少线程(当活跃线程数大于2倍的忙线程，且活跃线程数不小于最低线程数)
        if((live_thrd >= 2*busy_thrd) && live_thrd>poolp->min_thrd)
        {
            pthread_mutex_lock(&poolp->pool_mutex);
            poolp->waitexit_thrd_num++; 
            pthread_mutex_unlock(&poolp->pool_mutex);

            //通知空闲的线程去自杀
            pthread_cond_signal(&poolp->pool_cond_notemp);
        } 

       //2-2 增加线程(当任务数大于活跃线程数量时，且活跃线程数不大于最大线程数)
        if((task_num >= live_thrd) && live_thrd<poolp->max_thrd)
        {
            printf("manager add-----------\n");
            int add_cnt = 0;
           
            pthread_mutex_lock(&poolp->pool_mutex);
            //对max_thrd，一一检查可用的线程号 || 未生存的线程号,
            //增加 ONCE_ADD_THRD 个线程(最终数量超过 max_thrd 除外)
            for(i=0; (i<poolp->max_thrd)&&(add_cnt < ONCE_ADD_THRD)&&(poolp->live_thrd_num < poolp->max_thrd) ;i++)
            {
                if((poolp->threads[i] == 0)||(!ThreadLive_Detec(poolp->threads[i])))
                {
                    ret = pthread_create(&(poolp->threads[poolp->live_thrd_num]), NULL, ThreadPool_Worker, poolp);
                    if(ret < 0)
                    {
                        perror("manager add thread failed!");
                        exit(-1);
                     }
                    add_cnt++;
                    poolp->live_thrd_num++;
                    printf("new thread -----------------------\n");
                }
            }
            pthread_mutex_unlock(&poolp->pool_mutex);
        }
        #if 0
        int idle_thrdnum = poolp->live_thrd_num - poolp->busy_thrd_num;

        //1-check the live thread's num and busy thread's num
        //2-check if there are too many/ too few threads
        if((float)poolp->live_thrd_num > FACTOR* (float)poolp->busy_thrd_num ||(poolp->live_thrd_num > poolp->max_task))
        {
            printf("Threads is too many, exceed standard.\n");
            poolp->waitexit_thrd_num++;
        }
        else if((idle_thrdnum <= MIN_IDLE)||(poolp->live_thrd_num < poolp->min_thrd))
        {
            printf("Threads is too few, we should add some.\n");
            ret = pthread_create(&(poolp->threads[poolp->live_thrd_num]), NULL, ThreadPool_Worker, NULL);
            if(ret < 0)
            {
                perror("core thread create failed!");
                exit(-1);
            }
        }
        #endif
    }
    printf("Manager Dieing\n");
    pthread_exit(NULL); //return (void *)0;
}

/**
 * @func: detec if the thread is live
 * @arg:
 * @ret: ==0, not live // ==1, live
*/
int ThreadLive_Detec(pthread_t tid)
{    
    int kill_r = 0;
    kill_r = pthread_kill(tid, 0);
    //if(kill_r == ESRCH)  //if(kill_r == 3)
    if(kill_r == 3)
    {
        return 0;
    }
    return 1;
}
